package cn.foxtech.cloud.repository.controller;

import cn.craccd.mongoHelper.utils.CriteriaWrapper;
import cn.foxtech.cloud.core.domain.AjaxResult;
import cn.foxtech.cloud.core.exception.ServiceException;
import cn.foxtech.cloud.repo.comp.model.constants.ConstantRepoCompModel;
import cn.foxtech.cloud.repo.comp.model.constants.ConstantRepoCompModelObject;
import cn.foxtech.cloud.repo.comp.model.constants.ConstantRepoCompModelVersion;
import cn.foxtech.cloud.repo.comp.model.entity.RepoCompModelEntity;
import cn.foxtech.cloud.repo.comp.model.entity.RepoCompModelObjectEntity;
import cn.foxtech.cloud.repo.comp.model.entity.RepoCompModelVersionEntity;
import cn.foxtech.cloud.repo.comp.model.service.RepoCompModelService;
import cn.foxtech.cloud.repo.comp.model.service.RepoCompModelVersionService;
import cn.foxtech.cloud.repo.group.service.RepoGroupService;
import cn.foxtech.common.utils.bean.BeanMapUtils;
import cn.foxtech.common.utils.json.JsonUtils;
import cn.foxtech.common.utils.method.MethodUtils;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.security.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.*;

@RestController
@RequestMapping("/repository/component/model/version")
public class RepoCompModelVersionController {
    @Autowired
    private RepoCompModelService modelService;

    @Autowired
    private RepoCompModelVersionService versionService;

    @Autowired
    private RepoGroupService groupService;

    @RequiresPermissions("monitor:repo:query")
    @PostMapping("page")
    public AjaxResult getVersionPage(@RequestBody Map<String, Object> body) {
        return this.getList(body, true);
    }

    @RequiresPermissions("monitor:repo:query")
    @PostMapping("entities")
    public AjaxResult getVersionList(@RequestBody Map<String, Object> body) {
        return this.getList(body, false);
    }

    public AjaxResult getList(Map<String, Object> body, boolean isPage) {
        try {
            String username = SecurityUtils.getUsername();
            if (MethodUtils.hasEmpty(username)) {
                throw new ServiceException("获得登录用户信息失败!");
            }

            String modelId = (String) body.get(ConstantRepoCompModelVersion.field_model_id);

            if (MethodUtils.hasEmpty(modelId)) {
                throw new ServiceException("body参数缺失: modelId");
            }

            // 查询实体
            RepoCompModelEntity modelEntity = this.modelService.queryEntity(modelId);
            if (modelEntity == null) {
                throw new ServiceException("找不到对应的实体");
            }

            // 当前用户所属的组信息
            Set<String> groupIds = this.groupService.queryGroupIds(username);

            // 检查权限
            if (!username.equals(modelEntity.getOwnerId()) // 作者有权限
                    && !groupIds.contains(modelEntity.getGroupId()) // 群组成员有权限
                    && !username.equals("admin")// 管理员有权限
            ) {
                throw new ServiceException("只有 admin / owner / group member 有权限查看");
            }

            // 构造过滤器
            CriteriaWrapper criteriaWrapper = this.versionService.buildWrapper(body);

            if (isPage) {
                // 查询主数据
                Map<String, Object> data = this.versionService.queryPageList(criteriaWrapper, body);

                // 扩展信息
                Map<String, Object> result = this.extend(data, modelEntity);

                return AjaxResult.success(result);
            } else {
                // 查询主数据
                List<RepoCompModelVersionEntity> entityList = this.versionService.queryEntityList(criteriaWrapper);

                // 扩展信息
                List<Map<String, Object>> result = this.extend(entityList, modelEntity);

                return AjaxResult.success(result);
            }


        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    private Map<String, Object> extend(Map<String, Object> data, RepoCompModelEntity modelEntity) throws IOException {
        // 扩展信息
        String json = JsonUtils.buildJson(data);
        Map<String, Object> result = JsonUtils.buildObject(json, Map.class);
        List<Map<String, Object>> list = (List<Map<String, Object>>) result.get("list");
        for (Map<String, Object> map : list) {
            map.put(ConstantRepoCompModel.field_manufacturer, modelEntity.getManufacturer());
            map.put(ConstantRepoCompModel.field_device_type, modelEntity.getDeviceType());
        }

        return result;
    }

    private List<Map<String, Object>> extend(List<RepoCompModelVersionEntity> list, RepoCompModelEntity modelEntity) throws IOException {
        List<Map<String, Object>> resultList = new ArrayList<>();

        for (RepoCompModelVersionEntity entity : list) {
            Map<String, Object> map = BeanMapUtils.objectToMap(entity);
            map.put(ConstantRepoCompModel.field_manufacturer, modelEntity.getManufacturer());
            map.put(ConstantRepoCompModel.field_device_type, modelEntity.getDeviceType());
            map.put(ConstantRepoCompModel.field_group_id, modelEntity.getGroupId());
            map.put(ConstantRepoCompModel.field_group_name, modelEntity.getGroupName());
            resultList.add(map);
        }

        return resultList;
    }

    @RequiresPermissions("monitor:repo:query")
    @PostMapping("object/entities")
    public AjaxResult getOperateList(@RequestBody Map<String, Object> body) {
        try {
            String username = SecurityUtils.getUsername();
            if (MethodUtils.hasEmpty(username)) {
                throw new ServiceException("获得登录用户信息失败!");
            }

            String versionId = (String) body.get(ConstantRepoCompModelObject.field_version_id);

            if (MethodUtils.hasEmpty(versionId)) {
                throw new ServiceException("body参数缺失: versionId");
            }

            RepoCompModelVersionEntity versionEntity = this.versionService.queryVersionEntity(versionId);
            if (versionEntity == null) {
                throw new ServiceException("找不到对应的版本实体");
            }

            // 查询实体
            RepoCompModelEntity modelEntity = this.modelService.queryEntity(versionEntity.getModelId());
            if (modelEntity == null) {
                throw new ServiceException("找不到对应的组件实体");
            }

            // 当前用户所属的组信息
            Set<String> groupIds = this.groupService.queryGroupIds(username);

            // 检查权限
            if (!username.equals(modelEntity.getOwnerId()) // 作者有权限
                    && !groupIds.contains(modelEntity.getGroupId()) // 群组成员有权限
                    && !username.equals("admin")// 管理员有权限
            ) {
                throw new ServiceException("只有 admin / owner / group member 有权限查看");
            }

            List<Map<String, Object>> mapList = new ArrayList<>();
            for (RepoCompModelObjectEntity objectEntity : versionEntity.getObjects()) {
                if (objectEntity.getExtendParam() == null) {
                    objectEntity.setExtendParam(new HashMap<>());
                }

                String json = JsonUtils.buildJson(objectEntity);
                Map<String, Object> map = JsonUtils.buildObject(json, Map.class);
                map.put(ConstantRepoCompModelObject.field_version_id, versionEntity.getId());
                map.put(ConstantRepoCompModelVersion.field_model_id, modelEntity.getId());
                map.put(ConstantRepoCompModel.field_manufacturer, modelEntity.getManufacturer());
                map.put(ConstantRepoCompModel.field_device_type, modelEntity.getDeviceType());
                mapList.add(map);
            }

            return AjaxResult.success(mapList);


        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    @RequiresPermissions("monitor:repo:query")
    @PostMapping("object/entity")
    public AjaxResult getObjectEntity(@RequestBody Map<String, Object> body) {
        try {
            String username = SecurityUtils.getUsername();
            if (MethodUtils.hasEmpty(username)) {
                throw new ServiceException("获得登录用户信息失败!");
            }

            String versionId = (String) body.get(ConstantRepoCompModelObject.field_version_id);
            String operateId = (String) body.get(ConstantRepoCompModelObject.field_object_id);

            if (MethodUtils.hasEmpty(versionId, operateId)) {
                throw new ServiceException("body参数缺失: versionId, operateId");
            }

            RepoCompModelVersionEntity versionEntity = this.versionService.queryVersionEntity(versionId);
            if (versionEntity == null) {
                throw new ServiceException("找不到对应的版本实体");
            }

            // 查询实体
            RepoCompModelEntity modelEntity = this.modelService.queryEntity(versionEntity.getModelId());
            if (modelEntity == null) {
                throw new ServiceException("找不到对应的组件实体");
            }

            // 当前用户所属的组信息
            Set<String> groupIds = this.groupService.queryGroupIds(username);

            // 检查权限
            if (!username.equals(modelEntity.getOwnerId()) // 作者有权限
                    && !groupIds.contains(modelEntity.getGroupId()) // 群组成员有权限
                    && !username.equals("admin")// 管理员有权限
            ) {
                throw new ServiceException("只有 admin / owner / group member 有权限查看");
            }

            for (RepoCompModelObjectEntity objectEntity : versionEntity.getObjects()) {
                if (operateId.equals(objectEntity.getObjectId())) {
                    String json = JsonUtils.buildJson(objectEntity);
                    Map<String, Object> map = JsonUtils.buildObject(json, Map.class);
                    map.put(ConstantRepoCompModelObject.field_version_id, versionEntity.getId());
                    map.put(ConstantRepoCompModelVersion.field_model_id, modelEntity.getId());
                    map.put(ConstantRepoCompModel.field_manufacturer, modelEntity.getManufacturer());
                    map.put(ConstantRepoCompModel.field_device_type, modelEntity.getDeviceType());
                    return AjaxResult.success(map);
                }
            }

            return AjaxResult.error("找不到该操作实体");


        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    @PostMapping("entity")
    public AjaxResult createVersion(@RequestBody Map<String, Object> body) {
        try {
            String userName = SecurityUtils.getUsername();
            if (MethodUtils.hasEmpty(userName)) {
                throw new ServiceException("获得登录用户信息失败!");
            }

            // 提交代码
            RepoCompModelVersionEntity entity = this.versionService.uploadVersionEntity(userName, body);

            return AjaxResult.success(entity);

        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }
}
